package com.ruoyi.system.service.impl;

import java.util.*;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.constant.AuditActionConstant;
import com.ruoyi.system.constant.AuditModeConstant;
import com.ruoyi.system.constant.AuditResultConstant;
import com.ruoyi.system.constant.AuditStatusConstant;
import com.ruoyi.system.domain.AuditAssignee;
import com.ruoyi.system.domain.AuditRoute;
import com.ruoyi.system.domain.Leave;
import com.ruoyi.system.mapper.AuditRouteMapper;
import com.ruoyi.system.service.IAuditAssigneeService;
import com.ruoyi.system.service.IAuditNodeService;
import com.ruoyi.system.service.IAuditRouteService;
import com.ruoyi.system.service.ILeaveService;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.system.mapper.AuditRecordMapper;
import com.ruoyi.system.domain.AuditRecord;
import com.ruoyi.system.service.IAuditRecordService;

import javax.annotation.Resource;

/**
 *  审核记录Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-11-08
 */
@Service
public class AuditRecordServiceImpl extends ServiceImpl<AuditRecordMapper,AuditRecord> implements IAuditRecordService
{
    @Autowired
    private AuditRecordMapper auditRecordMapper;

    @Resource
    private IAuditAssigneeService auditAssigneeService;
    
    @Resource
    private IAuditRouteService auditRouteService;
    
    @Resource
    private IAuditNodeService auditNodeService;
    
    @Resource
    private ILeaveService leaveService;
    
    @Resource
    private ISysUserService userService;
    @Autowired
    private AuditRouteMapper auditRouteMapper;

    /**
     * 查询 审核记录
     * 
     * @param auditRecordId  审核记录主键
     * @return  审核记录
     */
    @Override
    public AuditRecord selectAuditRecordByAuditRecordId(String auditRecordId)
    {
        return auditRecordMapper.selectAuditRecordByAuditRecordId(auditRecordId);
    }

    /**
     * 查询 审核记录列表
     * 
     * @param auditRecord  审核记录
     * @return  审核记录
     */
    @Override
    public List<AuditRecord> selectAuditRecordList(AuditRecord auditRecord)
    {
        return auditRecordMapper.selectAuditRecordList(auditRecord);
    }

    /**
     * 新增 审核记录
     * 
     * @param auditRecord  审核记录
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertAuditRecord(AuditRecord auditRecord)
    {
        auditRecord.setCreateTime(DateUtils.getNowDate());
        auditRecord.setCreateBy(SecurityUtils.getUsername());
        int result = auditRecordMapper.insertAuditRecord(auditRecord);
        
        // 根据审核结果更新相关状态
        if (result > 0) {
            processAuditRecord(auditRecord);
        }
        
        return result;
    }

    /**
     * 处理审核记录逻辑
     * 
     * @param auditRecord 审核记录
     */
    private void processAuditRecord(AuditRecord auditRecord) {
        // 查询对应的审核人信息
        AuditAssignee auditAssignee = auditAssigneeService.selectAuditAssigneeByAssigneeId(
                auditRecord.getAuditAssigneeId());

        if (auditAssignee == null) {
            return;
        }
        
        // 查询对应的审核路径信息
        AuditRoute auditRoute = auditRouteService.selectAuditRouteByAuditRouteId(
                auditAssignee.getAuditRouteId());
        
        if (auditRoute == null) {
            return;
        }
        
        // 查询对应的请假信息
        Leave leave = leaveService.selectLeaveByLeaveId(auditRecord.getBusinessId());
        
        if (leave == null) {
            return;
        }
        
        // 如果审核拒绝
        if (AuditResultConstant.REJECTED.equals(auditRecord.getAuditResult())) { // 拒绝
            // 更新audit_assignee的审核状态为拒绝
            auditAssignee.setAuditStatus(AuditStatusConstant.REJECTED); // 已拒绝

            // 更新audit_route的审核状态为拒绝
            auditRoute.setAuditStatus(AuditStatusConstant.REJECTED);
            auditRouteService.updateAuditRoute(auditRoute);
            
            // 更新leave的审核状态为拒绝
            leave.setAuditStatus(AuditStatusConstant.REJECTED); // 拒绝
            leaveService.updateLeave(leave);
        } 
        // 如果审核驳回并指定驳回路径
        else if (AuditResultConstant.ROLLBACK.equals(auditRecord.getAuditResult())
                && auditRecord.getRollbackRouteId() != null) { // 驳回
            auditAssignee.setAuditStatus(AuditStatusConstant.CANCELLED);

            // 处理驳回逻辑
            processRollback(auditRecord, auditRoute, leave);
        }
        // 如果审核通过
        else if (AuditResultConstant.PASS.equals(auditRecord.getAuditResult())) { // 通过
            // 更新audit_assignee的审核状态为通过
            auditAssignee.setAuditStatus(AuditStatusConstant.APPROVED); // 已通过

            leave.setAuditStatus(AuditStatusConstant.PROCESSING);
            // 判断审核模式
            if (AuditModeConstant.OR_SIGN.equals(auditRoute.getAuditMode())) {
                // 或签模式：只要有一个审批人通过即可
                auditRoute.setAuditStatus(AuditStatusConstant.APPROVED);
                // 查找下一个审核路径
                processNextAuditRoute(leave, auditRoute);
            } else if (AuditModeConstant.AND_SIGN.equals(auditRoute.getAuditMode())) {
                // 会签模式：需要所有审批人都通过
                // 检查是否所有审批人都已通过
                if (isAllAssigneesApproved(auditRoute.getAuditRouteId())) {
                    auditRoute.setAuditStatus(AuditStatusConstant.APPROVED);

                    // 查找下一个审核路径
                    processNextAuditRoute(leave, auditRoute);
                }else {
                    auditRoute.setAuditStatus(AuditStatusConstant.PROCESSING);

                    leaveService.updateLeave(leave);
                }
            }
            auditRouteService.updateAuditRoute(auditRoute);
        }
        auditAssigneeService.updateAuditAssignee(auditAssignee);
    }
    
    /**
     * 处理驳回逻辑
     * 
     * @param auditRecord 审核记录
     * @param currentAuditRoute 当前审核路径
     * @param leave 请假信息
     */
    private void processRollback(AuditRecord auditRecord, AuditRoute currentAuditRoute, Leave leave) {
        Long rollbackRouteId = auditRecord.getRollbackRouteId();

        // 1. 要驳回到的路径
        AuditRoute rollbackRoute = auditRouteService.selectAuditRouteByAuditRouteId(rollbackRouteId);

        if (rollbackRoute == null) {
            return;
        }

        // 2. 重新生成从目标路径到当前路径的审核路径数据
        Long newCurrentRouteId = regenerateRoutes(leave, rollbackRoute, currentAuditRoute);

        // 3. 当前路径标记为驳回
        currentAuditRoute.setAuditStatus(AuditStatusConstant.REJECTED);
        auditRouteService.updateAuditRoute(currentAuditRoute);

        // 4. 更新leave的当前审核路径为驳回目标节点生成的新路径
        if (newCurrentRouteId != null) {
            leave.setCurrentAuditRouteId(newCurrentRouteId);
        } else {
            leave.setCurrentAuditRouteId(rollbackRouteId);
        }
        leaveService.updateLeave(leave);
    }
    
    /**
     * 重新生成指定范围内的审核路径
     * 
     * @param leave 请假信息
     * @param rollbackRoute 驳回目标路径
     * @param currentAuditRoute 当前审核路径
     */
    private Long regenerateRoutes(Leave leave, AuditRoute rollbackRoute, AuditRoute currentAuditRoute) {
        if (rollbackRoute == null || currentAuditRoute == null) {
            return null;
        }

        Integer fromOrder = rollbackRoute.getAuditOrder();
        Integer toOrder = currentAuditRoute.getAuditOrder();
        if (fromOrder == null || toOrder == null || fromOrder > toOrder) {
            return null;
        }

        // 后续审核路径的轮数+1
        if (currentAuditRoute.getRoundNo() != null) {
            auditRouteMapper.updateAuditRouteRoundNo(
                    leave.getLeaveId(),
                    leave.getAuditBusinessType(),
                    currentAuditRoute.getRoundNo(),
                    toOrder
            );
        }

        // 之前审核通过的设置为作废
        auditRouteMapper.cancelRoutesByOrderRange(
                leave.getLeaveId(),
                leave.getAuditBusinessType(),
                currentAuditRoute.getAuditRouteId(),
                fromOrder,
                toOrder,
                AuditStatusConstant.CANCELLED
        );

        // 获取指定范围内的审核路径模板
        List<AuditRoute> templates = auditRouteMapper.selectRollbackTemplates(
                leave.getLeaveId(),
                leave.getAuditBusinessType(),
                fromOrder,
                toOrder
        );
        if (templates == null || templates.isEmpty()) {
            return null;
        }

        List<AuditRoute> newRoutes = new ArrayList<>();
        List<List<AuditAssignee>> groupedAssignees = new ArrayList<>();

        for (AuditRoute template : templates) {
            if (template == null) {
                continue;
            }
            AuditRoute newRoute = new AuditRoute();
            newRoute.setBusinessId(leave.getLeaveId());
            newRoute.setAuditBusinessType(leave.getAuditBusinessType());
            newRoute.setAuditMode(template.getAuditMode());
            newRoute.setAuditRoleId(template.getAuditRoleId());
            newRoute.setCopyRoleIds(template.getCopyRoleIds());
            newRoute.setAuditOrder(template.getAuditOrder());
            newRoute.setRoundNo(currentAuditRoute.getRoundNo() + 1);
            newRoute.setAuditStatus(AuditStatusConstant.PENDING);
            newRoute.setCreateTime(DateUtils.getNowDate());
            newRoute.setUpdateTime(null);
            newRoutes.add(newRoute);

            List<AuditAssignee> assignees = new ArrayList<>();
            if (template.getAuditRoleId() != null) {
                List<com.ruoyi.common.core.domain.entity.SysUser> auditUsers =
                        userService.selectUserListByRoleId(template.getAuditRoleId());
                for (com.ruoyi.common.core.domain.entity.SysUser user : auditUsers) {
                    AuditAssignee assignee = new AuditAssignee();
                    assignee.setBusinessId(leave.getLeaveId());
                    assignee.setAuditBusinessType(leave.getAuditBusinessType());
                    assignee.setUserId(user.getUserId());
                    assignee.setActionType(AuditActionConstant.AUDIT);
                    assignee.setAuditStatus(AuditStatusConstant.PENDING);
                    assignee.setRoundNo(currentAuditRoute.getRoundNo() + 1);
                    assignee.setCreateTime(DateUtils.getNowDate());
                    assignee.setUpdateTime(null);
                    assignees.add(assignee);
                }
            }

            if (StringUtils.isNotEmpty(template.getCopyRoleIds())) {
                String[] copyRoles = template.getCopyRoleIds().split(",");
                for (String roleIdStr : copyRoles) {
                    if (StringUtils.isEmpty(roleIdStr)) {
                        continue;
                    }
                    Long roleId = Long.valueOf(roleIdStr.trim());
                    List<com.ruoyi.common.core.domain.entity.SysUser> copyUsers =
                            userService.selectUserListByRoleId(roleId);
                    for (com.ruoyi.common.core.domain.entity.SysUser user : copyUsers) {
                        AuditAssignee assignee = new AuditAssignee();
                        assignee.setBusinessId(leave.getLeaveId());
                        assignee.setAuditBusinessType(leave.getAuditBusinessType());
                        assignee.setUserId(user.getUserId());
                        assignee.setActionType(AuditActionConstant.COPY);
                        assignee.setAuditStatus(AuditStatusConstant.PENDING);
                        assignee.setRoundNo(currentAuditRoute.getRoundNo() + 1);
                        assignee.setCreateTime(DateUtils.getNowDate());
                        assignee.setUpdateTime(null);
                        assignees.add(assignee);
                    }
                }
            }
            groupedAssignees.add(assignees);
        }

        if (newRoutes.isEmpty()) {
            return null;
        }

        auditRouteService.insertAuditRoutes(newRoutes);

        List<AuditAssignee> allAssignees = new ArrayList<>();
        for (int i = 0; i < newRoutes.size(); i++) {
            AuditRoute newRoute = newRoutes.get(i);
            List<AuditAssignee> assignees = groupedAssignees.get(i);
            if (assignees == null || assignees.isEmpty()) {
                continue;
            }
            for (AuditAssignee assignee : assignees) {
                assignee.setAuditRouteId(newRoute.getAuditRouteId());
                allAssignees.add(assignee);
            }
        }

        if (!allAssignees.isEmpty()) {
            auditAssigneeService.insertAuditAssignees(allAssignees);
        }

        return newRoutes.get(0).getAuditRouteId();
    }

    /**
     * 检查指定审核路径的所有审批人是否都已通过
     * 
     * @param auditRouteId 审核路径ID
     * @return 是否都已通过
     */
    private boolean isAllAssigneesApproved(Long auditRouteId) {
        AuditAssignee queryAssignee = new AuditAssignee();
        queryAssignee.setAuditRouteId(auditRouteId);
        List<AuditAssignee> assignees = auditAssigneeService.selectAuditAssigneeList(queryAssignee);
        
        // 检查除了当前用户外其他所有审批人是否都已处理且通过
        for (AuditAssignee assignee : assignees) {
            // 如果有任何一个审批人未处理或处理状态不是通过，则返回false
            if (!Objects.equals(assignee.getUserId(), SecurityUtils.getUserId()) && !AuditStatusConstant.APPROVED.equals(assignee.getAuditStatus())) {
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 处理下一个审核路径
     * 
     * @param leave 当前请假信息
     * @param currentAuditRoute 当前审核路径
     */
    private void processNextAuditRoute(Leave leave, AuditRoute currentAuditRoute) {
        // 查找下一个审核顺序的审核路径
        AuditRoute nextAuditRoute = findNextAuditRoute(leave.getLeaveId(), currentAuditRoute.getAuditOrder());
        
        if (nextAuditRoute != null) {
            // 更新leave的currentAuditRouteId为下一个审核路径
            leave.setCurrentAuditRouteId(nextAuditRoute.getAuditRouteId());
        } else {
            // 没有下一个审核路径，表示整个审批流程结束，更新为已通过
            leave.setAuditStatus(AuditStatusConstant.APPROVED); // 通过
        }
        
        leaveService.updateLeave(leave);
    }
    
    /**
     * 查找下一个审核路径
     * 
     * @param businessId 业务ID
     * @param currentOrder 当前审核顺序
     * @return 下一个审核路径
     */
    private AuditRoute findNextAuditRoute(Long businessId, Integer currentOrder) {
        AuditRoute queryRoute = new AuditRoute();
        queryRoute.setBusinessId(businessId);
        queryRoute.setAuditOrder(currentOrder + 1);
        queryRoute.setAuditStatus(AuditStatusConstant.PENDING);
        List<AuditRoute> routes = auditRouteService.selectAuditRouteList(queryRoute);
        
        return routes.isEmpty() ? null : routes.get(0);
    }

    /**
     * 修改 审核记录
     * 
     * @param auditRecord  审核记录
     * @return 结果
     */
    @Override
    public int updateAuditRecord(AuditRecord auditRecord)
    {
        auditRecord.setUpdateTime(DateUtils.getNowDate());
        return auditRecordMapper.updateAuditRecord(auditRecord);
    }

    /**
     * 批量删除 审核记录
     * 
     * @param auditRecordIds 需要删除的 审核记录主键
     * @return 结果
     */
    @Override
    public int deleteAuditRecordByAuditRecordIds(String[] auditRecordIds)
    {
        return auditRecordMapper.deleteAuditRecordByAuditRecordIds(auditRecordIds);
    }

    /**
     * 删除 审核记录信息
     * 
     * @param auditRecordId  审核记录主键
     * @return 结果
     */
    @Override
    public int deleteAuditRecordByAuditRecordId(String auditRecordId)
    {
        return auditRecordMapper.deleteAuditRecordByAuditRecordId(auditRecordId);
    }
}